#include "hashtable.h"

#include <pthread.h>
#include <stdio.h>

// 哈希函数：使用简单的字符串哈希算法
unsigned int hash(const char *key) {
    unsigned int hash = 0;
    while (*key) {
        hash = (hash * 31) + (unsigned char)(*key);
        key++;
    }
    return hash % HASHTABLE_SIZE;
}

// 创建哈希表
HashTable *create_table() {
    HashTable *table = (HashTable *)malloc(sizeof(HashTable));
    if (!table) return NULL;

    for (int i = 0; i < HASHTABLE_SIZE; i++) {
        pthread_mutex_init(&table->mutexes[i], NULL);  // 初始化互斥锁
    }

    memset(table->table, 0, sizeof(table->table));
    return table;
}

// 销毁哈希表
void destroy_table(HashTable *table) {
    if (table) {
        for (int i = 0; i < HASHTABLE_SIZE; i++) {
            pthread_mutex_destroy(&table->mutexes[i]);  // 销毁互斥锁
        }

        for (int i = 0; i < HASHTABLE_SIZE; i++) {
            Node *node = table->table[i];
            while (node) {
                Node *tmp = node;
                node = node->next;
                free(tmp->key);
                free(tmp->value);
                free(tmp);
            }
        }

        free(table);
    }
}

// 插入键值对到哈希表
int insert(HashTable *table, const char *key, const void *value, size_t value_size) {
    unsigned int index = hash(key) % HASHTABLE_SIZE;
    pthread_mutex_lock(&table->mutexes[index]);  // 锁定对应的哈希桶

    Node *new_node = (Node *)malloc(sizeof(Node));
    if (!new_node) {
        pthread_mutex_unlock(&table->mutexes[index]);
        return -1;
    }

    new_node->key = strdup(key);  // 复制键
    if (!new_node->key) {
        free(new_node);
        pthread_mutex_unlock(&table->mutexes[index]);
        return -1;
    }

    new_node->value = malloc(value_size);
    if (!new_node->value) {
        free(new_node->key);
        free(new_node);
        pthread_mutex_unlock(&table->mutexes[index]);
        return -1;
    }

    memcpy(new_node->value, value, value_size);  // 复制值
    new_node->value_size = value_size;
    new_node->next = table->table[index];
    table->table[index] = new_node;

    pthread_mutex_unlock(&table->mutexes[index]);  // 解锁哈希桶
    return 0;
}

// 从哈希表中获取值
void *get(HashTable *table, const char *key) {
    unsigned int index = hash(key) % HASHTABLE_SIZE;
    pthread_mutex_lock(&table->mutexes[index]);  // 锁定对应的哈希桶

    Node *node = table->table[index];
    while (node) {
        if (strcmp(node->key, key) == 0) {
            pthread_mutex_unlock(&table->mutexes[index]);  // 解锁哈希桶
            return node->value;
        }
        node = node->next;
    }

    pthread_mutex_unlock(&table->mutexes[index]);  // 解锁哈希桶
    return NULL;
}

// 从哈希表中删除键值对
int remove_key(HashTable *table, const char *key) {
    unsigned int index = hash(key) % HASHTABLE_SIZE;
    pthread_mutex_lock(&table->mutexes[index]);  // 锁定对应的哈希桶

    Node *node = table->table[index];
    Node *prev = NULL;

    while (node) {
        if (strcmp(node->key, key) == 0) {
            if (prev) {
                prev->next = node->next;
            } else {
                table->table[index] = node->next;
            }
            free(node->key);
            free(node->value);
            free(node);
            pthread_mutex_unlock(&table->mutexes[index]);  // 解锁哈希桶
            return 0;
        }
        prev = node;
        node = node->next;
    }

    pthread_mutex_unlock(&table->mutexes[index]);  // 解锁哈希桶
    return -1;
}
